package elite.rpt.runNew;

import com.wisdge.dataservice.Result;
import elite.core.dataBase.DBMethod;
import elite.core.dataBase.OneDBPara;
import elite.core.dataBase.StateRsObj;
import elite.core.log.logCls;
import elite.core.log.logIF;
import elite.core.root.LogObj;
import elite.core.root.PublicVar;
import elite.core.root.StaticMethod;
import elite.core.staffInfo.OneStaff;
import elite.data.out.Excel.root.OneExcel;
import elite.rpt.run.TmpDB;
import elite.rpt.run.value.ValueInfo;
import elite.sysfun.dbfun.dbexec.procedure.ExecJSProcInfo;

import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.*;

public class RunOneNew {
    private String rptId;
    private LogObj logk;
    private ValueInfo rptRun;
    private OneExcel excelObj;
    private static final logIF log = logCls.getMe(RunOneNew.class);

    public RunOneNew(String rptId, String rptGrpId, Map<String, Object> para, OneStaff staff, LogObj logk) {
        this.rptRun = new ValueInfo(rptGrpId, rptId, staff, para);
        this.rptId = rptId;
        this.logk = logk;
        logk.AddHeadStr("New RPT");
        log.debug(logk.getLogStr() + " Init Rpt Finish RptId:" + rptId + " Para:" + StaticMethod.ObjectToJSON(para) + " DBPool:" + staff.UseDBName("") + " Token:" + staff.getLoginKey() + " LoginLang:" + staff.getLoginLang());
    }

    private Result RunOne(String fileName, HttpServletResponse respone, DataSource ds, String dbPool, String dbType, Map<String, Object> runStruct, AllSqls allSqlList) {
        long curBeginTime = System.currentTimeMillis();

        try {
            Map<String, Object> struct = runStruct;
            Result rt = this.DoBeforeSP(runStruct, ds, dbPool);
            if (rt.getCode() < 0) {
                log.error(this.logk.getLogStr() + " End Run New Report Id:" + this.rptId + " 存储过程运行失败:" + rt.getMessage());
                return new Result(-1, " Report Id:" + this.rptId + " 存储过程运行失败:" + rt.getMessage());
            }

            rt = this.rptRun.loadPublicNewStructSqlData(allSqlList, runStruct, ds, dbPool, dbType, this.logk);
            if (rt.getCode() < 0) {
                log.error(this.logk.getLogStr() + " End Run New Report Id:" + this.rptId + " 全局SQL运行失败:" + rt.getMessage());
                return new Result(-1, " Report Id:" + this.rptId + " 全局SQL运行失败:" + rt.getMessage());
            }

            if (this.rptRun.getMultiPageFlag() == 1) {
                String name = this.rptRun.getPubRun().getOnePubValue("MULTIPAGE", "SHEETNAME");
                if (name.trim().equals("")) {
                    name = "报表1";
                }

                this.excelObj = new OneExcel(1, name);
                NewSheetRoot mOne = new NewSheetRoot(this.excelObj, name, allSqlList, runStruct, this.rptRun);
                mOne.BeginRunOne(ds, dbPool, dbType, this.logk);

                for (int irt = this.rptRun.getPubRun().MoveNext("MULTIPAGE", this.logk); irt > 0; irt = this.rptRun.getPubRun().MoveNext("MULTIPAGE", this.logk)) {
                    name = this.rptRun.getPubRun().getOnePubValue("MULTIPAGE", "SHEETNAME");
                    if (name.trim().equals("")) {
                        name = "报表" + (irt + 1);
                    }

                    this.excelObj.newOneSheet(name);
                    mOne = new NewSheetRoot(this.excelObj, name, allSqlList, struct, this.rptRun);
                    mOne.BeginRunOne(ds, dbPool, dbType, this.logk);
                }
            } else {
                this.excelObj = new OneExcel(1, "报表");
                NewSheetRoot mOne = new NewSheetRoot(this.excelObj, "报表", allSqlList, runStruct, this.rptRun);
                mOne.BeginRunOne(ds, dbPool, dbType, this.logk);
            }

            rt = this.DoEndSP(struct, ds, dbPool);
            if (rt.getCode() < 0) {
                log.error(this.logk.getLogStr() + " End Run New Report Id:" + this.rptId + " 报表运行后存储过程运行失败:" + rt.getMessage());
            }
        } catch (Exception var17) {
            log.error(this.logk.getLogStr() + "New Report Id:" + this.rptId + " 报表异常错误:" + var17.toString(), var17);
        } catch (Error var18) {
            log.error(this.logk.getLogStr() + "New Report Id:" + this.rptId + " 报表异常错误:" + var18.toString(), var18);
        }

        int outFlag = -99;

        Result rs;
        try {
            if (fileName.trim().equals("")) {
                outFlag = this.excelObj.WriteToHttp(respone, this.logk);
            } else {
                outFlag = this.excelObj.writeToFile(fileName, this.logk);
            }

            rs = new Result(1);
        } catch (Exception var15) {
            log.error(this.logk.getLogStr() + "Report Id:" + this.rptId + " 报表生成异常错误:" + var15.toString(), var15);
            rs = new Result(-1, "报表生成异常错误:" + var15.toString());
        } catch (Error var16) {
            log.error(this.logk.getLogStr() + "Report Id:" + this.rptId + " 报表生成异常错误:" + var16.toString(), var16);
            rs = new Result(-1, "报表生成异常错误:" + var16.toString());
        }

        log.debug(this.logk.getLogStr() + " End Run Report Id:" + this.rptId + " UserTime:" + (System.currentTimeMillis() - curBeginTime) / 1000L + " outFlag:" + outFlag);
        return rs;
    }

    public Result RunOneRptInfoTest(String fileName, HttpServletResponse respone, String JSON, AllSqls allSqlList) {
        log.debug(this.logk.getLogStr() + "   Begin Run New  Report Id:" + this.rptId);
        String dbPool = this.rptRun.getStaff().UseDBName("");
        DataSource ds = PublicVar.getInstance().getDB(dbPool, 1, this.logk);
        if (ds == null) {
            log.error(this.logk.getLogStr() + " End Run New Report Id:" + this.rptId + " DBPool连接池未正确获取，DBPool:" + dbPool);
            return new Result(-1, " DBPool连接池未正确获取，DBPool:" + dbPool);
        } else {
            String dbType = PublicVar.getInstance().getOneDBPoolType(dbPool, this.logk);
            Map<String, Object> runStruct = StaticMethod.JSONStrToMap(JSON, this.logk);
            return this.RunOne(fileName, respone, ds, dbPool, dbType, runStruct, allSqlList);
        }
    }

    public Result RunOneRptInfo(String fileName, HttpServletResponse respone) {
        log.debug(this.logk.getLogStr() + "   Begin Run New  Report Id:" + this.rptId);
        String dbPool = this.rptRun.getStaff().UseDBName("");
        DataSource ds = PublicVar.getInstance().getDB(dbPool, 1, this.logk);
        if (ds == null) {
            log.error(this.logk.getLogStr() + " End Run New Report Id:" + this.rptId + " DBPool连接池未正确获取，DBPool:" + dbPool);
            return new Result(-1, " DBPool连接池未正确获取，DBPool:" + dbPool);
        } else {
            String dbType = PublicVar.getInstance().getOneDBPoolType(dbPool, this.logk);
            Result rt = this.loadNewRptStruct(ds, this.rptId);
            if (rt.getCode() < 0) {
                log.error(this.logk.getLogStr() + " End Run New Report Id:" + this.rptId + " 结构加载失败");
                return new Result(-1, " Report Id:" + this.rptId + " 结构加载失败");
            } else {
                Map<String, Object> runStruct = (Map) rt.getValue();
                AllSqls allSqlList = new AllSqls();
                Result rsSql = allSqlList.loadMe(ds, this.rptId, this.logk);
                if (rsSql.getCode() < 0) {
                    log.error(this.logk.getLogStr() + " 加载SQL信息失败");
                    return rsSql;
                } else {
                    return this.RunOne(fileName, respone, ds, dbPool, dbType, runStruct, allSqlList);
                }
            }
        }
    }

    private Result DoOneSP(String dbPool, DataSource ds, String spName, Map<String, Object> paraValues) {
        TmpDB mDBInfo = new TmpDB(spName);
        if (!mDBInfo.getDbPool().equals("")) {
            ds = PublicVar.getInstance().getDB(mDBInfo.getDbPool(), 0, this.logk);
            dbPool = mDBInfo.getDbPool();
            if (ds == null) {
                log.error(this.logk.getLogStr() + "存储过程指定连接池获取失败：" + mDBInfo.getDbPool());
                return new Result(-1, "存储过程指定连接池获取失败：" + mDBInfo.getDbPool());
            }
        }

        ExecJSProcInfo mDoProc = new ExecJSProcInfo();
        Result mrs = mDoProc.DoProcedure(mDBInfo.getOtherStr(), paraValues, ds, dbPool, this.logk);
        if (mrs.getCode() < 0) {
            log.info(this.logk.getLogStr() + " 执行报表运行前存储过程执行失败：" + spName + " Result:" + StaticMethod.ObjectToJSON(mrs));
            return mrs;
        } else {
            log.info(this.logk.getLogStr() + " 执行报表运行前存储过程执行完成：" + spName + " Result:" + StaticMethod.ObjectToJSON(mrs));
            this.rptRun.setProcedureValue((List) mrs.getValue());
            return mrs;
        }
    }

    private Result DoBeforeSP(Map<String, Object> mapStruct, DataSource ds, String dbPool) {
        if (mapStruct.containsKey("runProc")) {
            Map<String, Object> tmp = StaticMethod.getOneMapByKey(mapStruct, "runProc");
            if (tmp.containsKey("before")) {
                List<Map<String, Object>> tmpLst = StaticMethod.getMapOneListObj(tmp, "before");

                for (int i = 0; i < tmpLst.size(); ++i) {
                    Map<String, Object> onePro = (Map) tmpLst.get(i);
                    String spName = StaticMethod.getMapOneString(onePro, "name");
                    List<Map<String, Object>> paraList = StaticMethod.getMapOneListObj(onePro, "para");
                    Map<String, Object> paraValues = new HashMap();

                    for (int j = 0; j < paraList.size(); ++j) {
                        Map<String, Object> tp = (Map) paraList.get(i);
                        paraValues.put(StaticMethod.getMapOneString(tp, "name"), this.rptRun.ReplaceParaValue(StaticMethod.getMapOneString(tp, "value"), ds, this.logk));
                    }

                    Result oneRs = this.DoOneSP(dbPool, ds, spName, paraValues);
                    if (oneRs.getCode() < 0) {
                        return oneRs;
                    }
                }
            }
        }

        return new Result(1);
    }

    private Result DoEndSP(Map<String, Object> mapStruct, DataSource ds, String dbPool) {
        if (mapStruct.containsKey("runProc")) {
            Map<String, Object> tmp = StaticMethod.getOneMapByKey(mapStruct, "runProc");
            if (tmp.containsKey("after")) {
                List<Map<String, Object>> tmpLst = StaticMethod.getMapOneListObj(tmp, "after");

                for (int i = 0; i < tmpLst.size(); ++i) {
                    Map<String, Object> onePro = (Map) tmpLst.get(i);
                    String spName = StaticMethod.getMapOneString(onePro, "name");
                    List<Map<String, Object>> paraList = StaticMethod.getMapOneListObj(onePro, "para");
                    Map<String, Object> paraValues = new HashMap();

                    for (int j = 0; j < paraList.size(); ++j) {
                        Map<String, Object> tp = (Map) paraList.get(i);
                        paraValues.put(StaticMethod.getMapOneString(tp, "name"), this.rptRun.ReplaceParaValue(StaticMethod.getMapOneString(tp, "value"), ds, this.logk));
                    }

                    Result oneRs = this.DoOneSP(dbPool, ds, spName, paraValues);
                    if (oneRs.getCode() < 0) {
                        return oneRs;
                    }
                }
            }
        }

        return new Result(1);
    }

    private Result loadNewRptStruct(DataSource ds, String rptId) {
        log.debug(this.logk.getLogStr() + " 开始读取报表结构");
        Connection conn = DBMethod.getConnectWait(ds, this.logk);
        if (conn == null) {
            log.info(this.logk.getLogStr() + " 获取连接失败 ");
            return new Result(-1, "获取连接失败");
        } else {
            String rptStructStr = "";

            try {
                List<OneDBPara> para = new ArrayList();
                para.add(new OneDBPara(rptId, 0));
                String sql = "select COMPILESDATA,(select RESOURCES from sysc_i18n where MODULE_ID = 'REPORT' limit 1) as RESOURCES from T_RPTDATA where REPORTID=?";
                StateRsObj rs = DBMethod.getBoundRs(conn, sql, "sql_sys", para, this.logk);
                if (rs == null) {
                    log.error(this.logk.getLogStr() + " NewRpt 表结构错误:" + sql);
                    DBMethod.CloseConnect(conn, this.logk);
                    return new Result(-1, "表结构错误 ");
                }

                if (!DBMethod.RecNext(rs.getRs())) {
                    rs.closeMe();
                    DBMethod.CloseConnect(conn, this.logk);
                    return new Result(-1, "表结构错误,未找到对应的数据 " + sql + " para:" + para.toString());
                }

                rptStructStr = DBMethod.getStrValue(rs.getRs(), "COMPILESDATA");
                String rptI18nStr = DBMethod.getStrValue(rs.getRs(), "RESOURCES");

                log.debug(logk.getLogStr() + " Old表结构NewRptStruct COMPILESDATA:" + rptStructStr + " RESOURCES:" + rptI18nStr);

                String LoginLang = Objects.equals(this.rptRun.getStaff().getLoginLang(), "") ? "en_US" : this.rptRun.getStaff().getLoginLang();
                rptStructStr = RunOneNewI18n.doRPTI18n(rptStructStr, rptI18nStr, LoginLang);
                log.debug(logk.getLogStr() + " New表结构NewRptStruct COMPILESDATA:" + rptStructStr + " RESOURCES:" + rptI18nStr);

            } catch (Exception var8) {
                log.error(this.logk.getLogStr() + " 报表结构读取异常失败:" + var8.toString(), var8);
                DBMethod.CloseConnect(conn, this.logk);
                return new Result(-1, var8.toString());
            }

            DBMethod.CloseConnect(conn, this.logk);
            Map<String, Object> newRptStruct = StaticMethod.JSONStrToMap(rptStructStr, this.logk);
            if (newRptStruct.isEmpty()) {
                return new Result(-1, "报表结构错误:" + rptStructStr);
            } else {
                log.debug(this.logk.getLogStr() + "RPTID:" + rptId + " Struct:" + rptStructStr);
                return new Result(1, "", newRptStruct);
            }
        }
    }

}